package com.haiyou.oss.alibaba.service.impl;


import com.aliyun.oss.OSSClient;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.model.PutObjectRequest;
import com.aliyun.oss.model.PutObjectResult;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.auth.sts.AssumeRoleRequest;
import com.aliyuncs.auth.sts.AssumeRoleResponse;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.profile.DefaultProfile;
import com.google.gson.Gson;
import com.haiyou.oss.alibaba.properties.AliOSSProperties;
import com.haiyou.oss.alibaba.service.AliOSSService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Random;

/**
 * 阿里云OSS服务实现
 */
@Slf4j
@RequiredArgsConstructor
public class AliOSSServiceImpl implements AliOSSService {

    public static final String JPG = "jpg";
    public static final String PNG = "png";
    private final AliOSSProperties aliYunOSSProperties;

    @Deprecated
    @Override
    public String uploadJpg(InputStream inputStream) {
        try {
            // 把图片读入到内存中
            BufferedImage bufImg = ImageIO.read(inputStream);
            // 压缩代码
            // 存储图片文件byte数组
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            //防止图片变红
            BufferedImage newBufferedImage = new BufferedImage(bufImg.getWidth(), bufImg.getHeight(), BufferedImage.TYPE_INT_RGB);
            newBufferedImage.createGraphics().drawImage(bufImg, 0, 0, Color.WHITE, null);
            //先转成jpg格式来压缩,然后在通过OSS来修改成源文件本来的后缀格式
            ImageIO.write(newBufferedImage, JPG, bos);
            //获取输出流
            inputStream = new ByteArrayInputStream(bos.toByteArray());
        } catch (IOException e) {
            e.printStackTrace();
        }
        return upLoad(inputStream, JPG);
    }

    @Deprecated
    @Override
    public String uploadPng(InputStream inputStream) {
        return upLoad(inputStream, PNG);
    }

    @Override
    @Deprecated
    public String upLoad(InputStream inputStream, String format) {
        String path = System.currentTimeMillis() + "." + format;
        return ossUpload(inputStream, path);
    }

    @Override
    @Deprecated
    public String upLoadFile(InputStream inputStream, String fileName) {
        return ossUpload(inputStream, fileName);
    }

    @Override
    public String upLoadBase64(byte[] imageByte) {
        OSSClient ossClient = new OSSClient(aliYunOSSProperties.getEndpoint(), aliYunOSSProperties.getAccessKeyId(), aliYunOSSProperties.getAccessSecret());
        try {
            ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(imageByte);
            String path = getAccessUrl() + "/" + System.currentTimeMillis() + "." + JPG;
            ossClient.putObject(aliYunOSSProperties.getBucketName(), path, byteArrayInputStream);
        } catch (OSSException oe) {
            log.error("OSS文件上传失败：{}", oe.getMessage());
        } finally {
            ossClient.shutdown();
        }
        throw new RuntimeException("OSS文件上传失败");
    }

    @Override
    public String uploadVideo(MultipartFile file) throws IOException {
        return ossUploadFile(file, "oss_video");
    }

    @Override
    public String uploadImage(MultipartFile file) throws IOException {
        return ossUploadFile(file, "oss_images");
    }

    @Override
    public String stsToken() {

        if (StringUtils.isEmpty(aliYunOSSProperties.getRoleArn())) {
            throw new RuntimeException("请配置roleArn");
        }

        //构建一个阿里云客户端，用于发起请求。
        //构建阿里云客户端时需要设置AccessKey ID和AccessKey Secret。
        DefaultProfile profile = DefaultProfile.getProfile("cn-hangzhou"
                , aliYunOSSProperties.getAccessKeyId()
                , aliYunOSSProperties.getAccessSecret());
        IAcsClient client = new DefaultAcsClient(profile);

        //构造请求，设置参数。关于参数含义和设置方法，请参见API参考。
        AssumeRoleRequest request = new AssumeRoleRequest();
        // 固定
        request.setRegionId("cn-hangzhou");
        request.setRoleArn(aliYunOSSProperties.getRoleArn());
        // 随便写
        request.setRoleSessionName("sts");
        request.setDurationSeconds(2000L); // 设置凭证有效时间
        //发起请求，并得到响应。
        try {
            AssumeRoleResponse response = client.getAcsResponse(request);
            String result = new Gson().toJson(response);
            log.info("响应结果：[{}]", result);
            return result;
        } catch (ClientException e) {
            log.error("获取sts异常：errCode=[{}],errMsg=[{}],异常信息：", e.getErrCode(), e.getErrMsg(), e);
            throw new RuntimeException(e.getErrMsg());
        }

    }

    // ------------------------------------------------------

    private String getAccessUrl() {
        return "https://" + aliYunOSSProperties.getBucketName() + "." + aliYunOSSProperties.getEndpoint();
    }

    private String ossUpload(InputStream inputStream, String path) {
        log.info("------OSS文件上传开始--------");
        OSSClient client = new OSSClient(aliYunOSSProperties.getEndpoint(), aliYunOSSProperties.getAccessKeyId(), aliYunOSSProperties.getAccessSecret());
        try {
            PutObjectRequest putObjectRequest = new PutObjectRequest(aliYunOSSProperties.getBucketName(), path, inputStream);
            PutObjectResult result = client.putObject(putObjectRequest);
            if (result != null) {
                String filePath = getAccessUrl() + "/" + path;
                log.info("------OSS文件上传成功------------->");
                log.info(filePath);
                return filePath;
            }
        } catch (OSSException oe) {
            log.error("OSS文件上传失败：{}", oe.getMessage());
        } finally {
            if (client != null) {
                client.shutdown();
            }
        }
        throw new RuntimeException("OSS文件上传失败");
    }

    private String ossUploadFile(MultipartFile file, String folder) throws IOException {
        String originalFilename = file.getOriginalFilename();
        String substring = originalFilename.substring(originalFilename.lastIndexOf(".")).toLowerCase();
        Random random = new Random();
        String name = random.nextInt(10000) + System.currentTimeMillis() + substring;
        try {
            InputStream stream = file.getInputStream();
            String filename = folder + "/" + name;
            OSSClient client = new OSSClient(aliYunOSSProperties.getEndpoint(), aliYunOSSProperties.getAccessKeyId(), aliYunOSSProperties.getAccessSecret());
            PutObjectResult result = client.putObject(aliYunOSSProperties.getBucketName(), filename, stream);
            log.info("返回结果->{}", result);
            client.shutdown();
            String ossUrl = getAccessUrl() + "/" + filename;
            log.info("返回地址 -> ossUrl={}", ossUrl);
            return ossUrl;
        } catch (Exception e) {
            log.error("上传文件失败：{}", e.getMessage());
            throw new IOException("上传文件失败");
        }
    }
}
